home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Special 16
/
AMIGAplus Sonderheft 16 (1998)(ICP)(DE)[!].iso
/
pd
/
anwendungen
/
ispell-3.1.18bin
/
interfaces
/
guispell-1.1
/
guispell.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-21
|
20KB
|
676 lines
/*
* This is GUISpell, the GadTool Front End for ISpell.
* You must have AmigaOS release 2.04 (with ARexx running) and
* `ISpell Version 3.1ljr with ARexx Server Mode, Thu Dec 27 04:16:35 1990'
* or later.
*
* Special thanks to Mike Schwartz for his PD GadTools Example
* that was posted to alt.sources.amiga on `11 Nov 91 12:14:43 PST'
* <mykes.8924@amiga0.SF-Bay.ORG>. You will note that some chunks
* below were ripped right out of his PD posting. Thanks!
* [Note: I don't like names that shout at me, so I removed all the
* loud typedefs... :-]
*
* Thanks to Eddy Carroll for Small.a (I now use cres.o, but thanks).
* Thanks to Michael Jansson for smallIFFparse (a sub-set of IFFparse
* that is Freely Redistributable) and sample code.
*
* This program makes use of many 2.04 features and may be used as
* an example of how to use iffparse.library, gadtools.library,
* MinRexx (by Radical Eye Software, Thanks!), clipboard hooks,
* public screen features and commodities.library.
*
* This work is Copyright © 1991, 1992 Loren J. Rittle (rittle@comm.mot.com)
* This software may be freely distributed and redistributed,
* for non-commercial purposes, provided this notice is included.
* You have the right to use the information contained within this
* document/program in any way that you see fit, as long as you quote
* this as the source of the information. You have the right to compile
* and run the program that is generated for any purpose. All other
* rights (most notably commercial ones) are reserved by the author.
*
* DISCLAIMER:
* "This software is provided 'as-is', without warranty of any kind,
* either expressed or implied. In no event will I, Loren J. Rittle,
* be liable for direct, indirect, incidental or consequential damages
* or data loss resulting from the use or application of this software.
* The entire risk as to the results and performance of this software
* is assumed by you."
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* There, how's that for legal mush? :-) Just trying to cover my...
*
* Loren J. Rittle
* rittle@comm.mot.com
* Sun Dec 08 21:19:13 1991
*/
#include <string.h>
#pragma msg 148 ignore push
#pragma msg 149 ignore push
#pragma msg 61 ignore push
#include <devices/clipboard.h>
#include <proto/all.h>
#pragma msg 149 pop
#pragma msg 61 pop
#include "libraries.h"
#include "error.h"
#include "minrexx.h"
#include "textclip.h"
extern long __builtin_getreg (int);
extern void __builtin_putreg (int, long);
#define REG_A4 12
extern char *_ProgramName;
#define VERSION "GUISpell 1.1 (26.9.92)"
#define NICE_VERSION "GUISpell-1.1 (" __DATE__ " " __TIME__ ")"
static char Version_ID[] = "$VER: " VERSION;
char *listText[512];
char *initListText[] =
{
NICE_VERSION,
"This is a freely distributable version",
"Copyright \xa9 1991, 1992 Loren J. Rittle",
"",
"GUISpell is the premier GUI front-end",
"to ISpell 3.3LJR (or later) with ARexx",
"Server Mode, for AmigaOS Release 2.04.",
"",
"If you use this software, please mail",
"the author at rittle@comm.mot.com, so I",
"can inform you of bugs and upgrades.",
0,
};
struct List lvList;
struct Gadget *gList;
struct Window *window;
struct Screen *screen;
APTR vi;
void *memory;
struct IOClipReq *ClipReq;
struct MsgPort *ClipPort;
struct Hook ClipHook;
struct ClipHookMsg ClipHookMsg = {0, CMD_UPDATE, 0};
struct Task *Task;
ULONG ClipAlertSignalNum = -1;
BOOL done;
int auto_clip;
int lookup_type;
struct TextAttr topaz80 = {"topaz.font", 8, 0, 0};
char *cycleText[] = {"Spell", "Reg exp", "Exact", 0};
struct TagItem nullTags[] = {TAG_DONE, 0};
struct TagItem cycleTags[] = {GTCY_Labels, (int) &cycleText[0], GTBB_Recessed, FALSE, TAG_DONE, 0};
struct TagItem listviewTags[] = {GTLV_Labels, (int) &lvList, GTLV_ReadOnly, FALSE, GTLV_ScrollWidth, 16, TAG_DONE, 0};
struct TagItem stringTags[] = {GTTX_CopyText, TRUE, GTTX_Border, FALSE, TAG_DONE, 0};
struct
{
struct TagItem *tags;
ULONG kind;
UWORD left, top, width, height;
ULONG flags;
char *text;
struct Gadget *object;
} gads[] =
{
{cycleTags, CYCLE_KIND, 121, 13, 90, 12, NG_HIGHLABEL, "Lookup Style:", 0},
{nullTags, CHECKBOX_KIND, 310, 13, 80, 12, NG_HIGHLABEL, "Auto-Clip:", 0},
{listviewTags, LISTVIEW_KIND, 20, 44, 360, 92, NG_HIGHLABEL | PLACETEXT_ABOVE, "", 0},
{nullTags, BUTTON_KIND, 234, 27, 81, 12, NG_HIGHLABEL | PLACETEXT_IN,"From Clip", 0},
{nullTags, BUTTON_KIND, 325, 27, 65, 12, NG_HIGHLABEL | PLACETEXT_IN,"To Clip", 0},
{nullTags, BUTTON_KIND, 350, 13, 40, 12, NG_HIGHLABEL | PLACETEXT_IN,"Add", 0},
{stringTags, STRING_KIND, 10, 27, 180, 12, NG_HIGHLABEL, "", 0},
{nullTags, BUTTON_KIND, 200, 27, 24, 12, NG_HIGHLABEL | PLACETEXT_IN,"Do", 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
};
#define LOOKUP_STYLE_ID 0
#define AUTO_CLIP_ID 1
#define WORD_LIST_ID 2
#define FROM_CLIP_ID 3
#define TO_CLIP_ID 4
#define ADD_WORD_ID 5
#define USER_WORD_ID 6
#define DO_ID 7
int main (int argc, char *argv[]);
void SubmitCheckRequest (int type, char *word);
void UpdateList (struct RexxMsg *msg);
void ProcessGadget (UWORD id, UWORD code);
void GadgetUp (struct IntuiMessage *m);
void *CreateList (struct List *list, char *array[]);
struct Gadget *CreateGadgets (void);
void OpenAll (void);
void CloseAll (void);
void rexxdisp (struct RexxMsg *msg, struct rexxCommandList *dat, char *p);
void rexxjump (struct RexxMsg *msg, char *p);
void rexxcheck (struct RexxMsg *msg, char *p);
/* void rexxquickcheck (struct RexxMsg *msg, char *p);
//void rexxlookup (struct RexxMsg *msg, char *p);
//void rexxcheckmode (struct RexxMsg *msg, char *p);
//void rexxautomode (struct RexxMsg *msg, char *p);
//void rexxzoommode (struct RexxMsg *msg, char *p);
//void rexxzoomwindow (struct RexxMsg *msg, char *p); */
void rexxcurrenttext (struct RexxMsg *msg, char *p);
void rexxcheckcallbackhook (struct RexxMsg *msg, char *p);
void invokerexxcheckcallbackhook (void);
void rexxversion (struct RexxMsg *msg, char *p);
void rexxexit (struct RexxMsg *msg, char *p);
struct rexxCommandList rcl[] =
{
{"check", &rexxcheck},
{"jump", &rexxjump},
{"currenttext", &rexxcurrenttext},
{"checkcallbackhook", &rexxcheckcallbackhook},
{"version", &rexxversion},
{"exit", &rexxexit},
{NULL, NULL}
};
/* This is really kludged up to get it to work under SAS/C 5.10b
with cres.o. This code is unportable between compilers and
in fact may fail with other versions of SAS/C. */
ULONG __asm ClipChange (register __a0 struct Hook *hook,
register __a4 void *junk)
{
__builtin_putreg (REG_A4, (long) hook->h_SubEntry);
Signal (Task, 1 << ClipAlertSignalNum);
return 0;
}
int main (int argc, char *argv[])
{
long rexxbit;
OnError (&CloseAll);
{
int i;
for (i = 0; initListText[i]; i++)
listText[i] = initListText[i];
}
OpenAll ();
if (!(rexxbit = upRexxPort ("GUISpell", rcl, 0, &rexxdisp)))
Error ("ss", _ProgramName, ": MinRexx had a problem.\n");
while (!done)
{
struct IntuiMessage *m;
long returnbits = Wait ((1 << window->UserPort->mp_SigBit) | rexxbit |
(1 << ClipAlertSignalNum) | SIGBREAKF_CTRL_C);
if (returnbits & SIGBREAKF_CTRL_C)
done = 1;
if (returnbits & rexxbit)
dispRexxPort ();
if ((returnbits & (1 << ClipAlertSignalNum)) && auto_clip)
{
char buffer[256];
if (TextFromClip (buffer, 256) && !strchr (buffer, ' '))
{
static struct TagItem tags[] = {GTST_String, 0, TAG_DONE, 0};
tags[0].ti_Data = (ULONG) buffer;
GT_SetGadgetAttrsA(gads[USER_WORD_ID].object, window, NULL, tags);
SubmitCheckRequest (lookup_type, ((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
}
}
if (returnbits & (1 << window->UserPort->mp_SigBit))
while (m = GT_GetIMsg (window->UserPort))
{
struct IntuiMessage msg = *m;
GT_ReplyIMsg (m);
switch (msg.Class)
{
case IDCMP_GADGETUP:
if (msg.Code == 0x09)
{
}
if (msg.Code == 0x5f)
{
}
else
ProcessGadget (((struct Gadget *) msg.IAddress)->GadgetID, msg.Code);
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh (window);
GT_EndRefresh (window, TRUE);
break;
case IDCMP_CLOSEWINDOW:
done = 1;
break;
default:
break;
}
}
}
CloseAll ();
return 0;
}
void SubmitCheckRequest (int lookup_type, char *word)
{
char buffer[256];
static char *rexxcommandname[] = {"check ", "lookup ", "quickcheck ", "add "};
if (lookup_type > 3)
{
DisplayBeep (0);
return;
}
strcpy (buffer, rexxcommandname[lookup_type]);
strncat (buffer, word, 240);
if (!sendSimpleCmd (buffer, "IRexxSpell", &UpdateList, NULL, NULL, NULL))
DisplayBeep (0);
}
void UpdateList (struct RexxMsg *msg)
{
static struct TagItem tags[] = {GTLV_Labels, ~0, TAG_DONE, 0};
static struct TagItem tags2[] = {GTLV_Labels, (int) &lvList, GTLV_Top, 0, TAG_DONE, 0};
static char buffer[513];
if (!msg->rm_Result1 && msg->rm_Result2)
{
GT_SetGadgetAttrsA (gads[WORD_LIST_ID].object, window, NULL, tags);
if (((struct RexxArg *) (msg->rm_Result2-8))->ra_Length > 512)
{
memcpy (buffer, (char *) msg->rm_Result2, 512);
buffer[512] = '\0';
}
else
{
memcpy (buffer, (char *) msg->rm_Result2,
((struct RexxArg *) (msg->rm_Result2-8))->ra_Length);
buffer[((struct RexxArg *) (msg->rm_Result2-8))->ra_Length] = '\0';
}
{
int a, b = 0;
listText[b++] = &buffer[0];
for (a = 0; buffer[a]; a++)
if (buffer[a] == ' ')
{
if (buffer[a+1])
listText[b++] = &buffer[a+1];
buffer[a] = '\0';
}
listText[b] = 0;
}
if (memory)
{
FreeVec (memory);
memory = 0;
}
memory = CreateList (&lvList, &listText[0]);
GT_SetGadgetAttrsA (gads[WORD_LIST_ID].object, window, NULL, tags2);
DeleteArgstring ((char *) msg->rm_Result2);
}
else
DisplayBeep (0);
}
void ProcessGadget (UWORD id, UWORD code)
{
switch (id)
{
case LOOKUP_STYLE_ID:
lookup_type = code;
break;
case AUTO_CLIP_ID:
auto_clip = gads[id].object->Flags & SELECTED;
break;
case WORD_LIST_ID:
{
static struct TagItem tags[] = {GTST_String, 0, TAG_DONE, 0};
tags[0].ti_Data = (ULONG) listText[code];
GT_SetGadgetAttrsA(gads[USER_WORD_ID].object, window, NULL, tags);
if (auto_clip)
TextToClip (((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
invokerexxcheckcallbackhook ();
break;
}
case FROM_CLIP_ID:
{
char buffer[256];
if (TextFromClip (buffer, 256))
{
static struct TagItem tags[] = {GTST_String, 0, TAG_DONE, 0};
tags[0].ti_Data = (ULONG) buffer;
GT_SetGadgetAttrsA(gads[USER_WORD_ID].object, window, NULL, tags);
if (!strchr (buffer, ' '))
SubmitCheckRequest (lookup_type, ((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
}
break;
}
case TO_CLIP_ID:
TextToClip (((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
break;
case ADD_WORD_ID:
SubmitCheckRequest (3, ((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
break;
case DO_ID:
case USER_WORD_ID:
SubmitCheckRequest (lookup_type, ((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
break;
default:
break;
}
}
void *CreateList (struct List *list, char *array[])
{
short i;
struct Node *np, *start_np;
NewList (list);
for (i = 0; array[i]; i++)
;
start_np = AllocVec (sizeof (struct Node) * i, 0);
if (!start_np)
Error ("ss", _ProgramName, ": No free memory!\n");
for (i = 0, np = start_np; array[i]; i++, np++)
{
np->ln_Name = (APTR) array[i];
np->ln_Pri = 0;
AddTail (list, np);
}
return start_np;
}
struct Gadget *CreateGadgets (void)
{
struct Gadget *gadget, *glist = 0;
short i;
struct NewGadget ng;
gadget = CreateContext (&glist);
if (!gadget)
Error ("ss", _ProgramName, ": Can't CreateContext\n");
for (i = 0; gads[i].tags; i++)
{
ng.ng_GadgetID = i;
ng.ng_TextAttr = &topaz80;
ng.ng_VisualInfo = vi;
ng.ng_LeftEdge = gads[i].left;
ng.ng_TopEdge = gads[i].top;
ng.ng_Width = gads[i].width;
ng.ng_Height = gads[i].height;
ng.ng_GadgetText = gads[i].text;
ng.ng_Flags = gads[i].flags;
gads[i].object = gadget = CreateGadgetA (gads[i].kind, gadget, &ng, gads[i].tags);
if (!gadget)
Error ("ss", _ProgramName, ": Can't CreateGadget\n");
}
return glist;
}
void OpenAll (void)
{
static struct TagItem tags[] = {GTLV_Labels, ~0, TAG_DONE, 0};
static WORD zoom_data[4] = {0, 0, 400, 43};
static struct TagItem wtags[] =
{
WA_Left, 0, WA_Top, 0, WA_Width, 400, WA_Height, 143,
WA_MinWidth, 400, WA_MinHeight, 43, WA_MaxWidth, -1, WA_MaxHeight, -1,
WA_DetailPen, 0, WA_BlockPen, 3, WA_IDCMP,
IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW|BUTTONIDCMP|CYCLEIDCMP|LISTVIEWIDCMP,
WA_Gadgets, 0 /*set below*/, WA_PubScreen, 0, /*set below*/
WA_Title, (ULONG)"GUISpell-1.1", WA_SuperBitMap, 0,
WA_SizeGadget, FALSE, WA_DragBar, TRUE, WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE, WA_Backdrop, FALSE, WA_ReportMouse, FALSE,
WA_Borderless, FALSE, WA_Activate, TRUE, WA_RMBTrap, FALSE,
WA_SimpleRefresh, TRUE, WA_Zoom, (ULONG)zoom_data, WA_RMBTrap, TRUE, TAG_DONE, 0
};
OpenLibraries ();
screen = LockPubScreen ("CygnusEdScreen1");
if (!screen)
screen = LockPubScreen ("Workbench");
if (!screen)
Error ("ss", _ProgramName, ": Can't Lock WB Screen!\n");
vi = GetVisualInfoA (screen, TAG_DONE);
if (!vi)
Error ("ss", _ProgramName, ": Can't GetVisualInfoA\n");
memory = CreateList (&lvList, &listText[0]);
gList = CreateGadgets ();
wtags[11].ti_Data = (ULONG) gList;
wtags[12].ti_Data = (ULONG) screen;
window = OpenWindowTagList (NULL, wtags);
UnlockPubScreen (0, screen);
if (!window)
Error ("ss", _ProgramName, ": Can't open window\n");
GT_RefreshWindow (window, NULL);
GT_SetGadgetAttrsA (gads[WORD_LIST_ID].object, window, NULL, tags);
Task = FindTask (0);
if ((ClipAlertSignalNum = AllocSignal (-1)) == -1)
Error ("ss", _ProgramName, ": Can't get a signal\n");
if (!(ClipPort = CreatePort (0L, 0L)))
Error ("ss", _ProgramName, ": Can't create port\n");
if (!(ClipReq = (struct IOClipReq *) CreateExtIO (ClipPort, sizeof (*ClipReq))))
Error ("ss", _ProgramName, ": Can't create ExtIO\n");
if (OpenDevice ("clipboard.device", 0L, (struct IORequest *) ClipReq, 0L))
Error ("ss", _ProgramName, ": Can't open clipboard device\n");
ClipReq->io_Command = CBD_CHANGEHOOK;
ClipReq->io_Length = 1;
ClipReq->io_Data = (void *) &ClipHook;
ClipHook.h_Entry = &ClipChange;
ClipHook.h_SubEntry = (ULONG (*)()) __builtin_getreg (REG_A4);
ClipHook.h_Data = &ClipHookMsg;
if (DoIO ((struct IORequest *) ClipReq))
Error ("ss", _ProgramName, ": Can't install clipboard hook\n");
}
void CloseAll (void)
{
struct IntuiMessage *msg;
if (ClipReq)
{
ClipReq->io_Command = CBD_CHANGEHOOK;
ClipReq->io_Length = 0;
ClipReq->io_Data = (void *) &ClipHook;
if (DoIO ((struct IORequest *) ClipReq))
Warning ("ss", _ProgramName, ": Can't deinstall clipboard hook (crash soon... :-)\n");
if (ClipReq->io_Device)
CloseDevice ((struct IORequest *)ClipReq);
DeleteExtIO ((struct IORequest *)ClipReq);
}
if (ClipPort)
DeletePort (ClipPort);
if (ClipAlertSignalNum != -1)
FreeSignal (ClipAlertSignalNum);
dnRexxPort ();
if (window)
{
while (msg = (struct IntuiMessage *) GT_GetIMsg (window->UserPort))
GT_ReplyIMsg (msg);
CloseWindow (window);
window = 0;
}
if (vi)
{
FreeVisualInfo (vi);
vi = 0;
}
if (gList)
{
FreeGadgets (gList);
gList = 0;
}
if (memory)
{
FreeVec (memory);
memory = 0;
}
CloseLibraries ();
}
void rexxdisp (struct RexxMsg *msg, struct rexxCommandList *dat, char *p)
{
(*(dat->userdata)) (msg, p);
}
void rexxjump (struct RexxMsg *msg, char *p)
{
struct IntuiMessage *Imsg;
static struct TagItem tags[] = {GTLV_Labels, ~0, TAG_DONE, 0};
static WORD zoom_data[4] = {0, 0, 400, 43};
static struct TagItem wtags[] =
{
WA_Left, 0, WA_Top, 0, WA_Width, 400, WA_Height, 143,
WA_MinWidth, 400, WA_MinHeight, 43, WA_MaxWidth, -1, WA_MaxHeight, -1,
WA_DetailPen, 0, WA_BlockPen, 3, WA_IDCMP,
IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW|BUTTONIDCMP|CYCLEIDCMP|LISTVIEWIDCMP,
WA_Gadgets, 0 /*set below*/, WA_PubScreen, 0, /*set below*/
WA_Title, (ULONG)"GUISpell-1.1", WA_SuperBitMap, 0,
WA_SizeGadget, FALSE, WA_DragBar, TRUE, WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE, WA_Backdrop, FALSE, WA_ReportMouse, FALSE,
WA_Borderless, FALSE, WA_Activate, TRUE, WA_RMBTrap, FALSE,
WA_SimpleRefresh, TRUE, WA_Zoom, (ULONG)zoom_data, WA_RMBTrap, TRUE, TAG_DONE, 0
};
if (window)
{
while (Imsg = (struct IntuiMessage *) GT_GetIMsg (window->UserPort))
GT_ReplyIMsg (Imsg);
CloseWindow (window);
window = 0;
}
if (vi)
{
FreeVisualInfo (vi);
vi = 0;
}
if (gList)
{
FreeGadgets (gList);
gList = 0;
}
screen = LockPubScreen (p);
if (!screen)
screen = LockPubScreen ("Workbench");
if (!screen)
Error ("ss", _ProgramName, ": Can't Lock WB Screen!\n");
vi = GetVisualInfoA (screen, TAG_DONE);
if (!vi)
Error ("ss", _ProgramName, ": Can't GetVisualInfoA\n");
gList = CreateGadgets ();
wtags[11].ti_Data = (ULONG) gList;
wtags[12].ti_Data = (ULONG) screen;
window = OpenWindowTagList (NULL, wtags);
UnlockPubScreen (0, screen);
if (!window)
Error ("ss", _ProgramName, ": Can't open window\n");
GT_RefreshWindow (window, NULL);
GT_SetGadgetAttrsA (gads[WORD_LIST_ID].object, window, NULL, tags);
}
void rexxcheck (struct RexxMsg *msg, char *p)
{
static struct TagItem tags[] = {GTST_String, 0, TAG_DONE, 0};
tags[0].ti_Data = (ULONG) p;
GT_SetGadgetAttrsA(gads[USER_WORD_ID].object, window, NULL, tags);
SubmitCheckRequest (0, ((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
replyRexxCmd (msg, 0L, 0L, "ok");
}
void rexxcurrenttext (struct RexxMsg *msg, char *p)
{
replyRexxCmd (msg, 0L, 0L, ((struct StringInfo *)gads[USER_WORD_ID].object->SpecialInfo)->Buffer);
}
char checkcallbackhookcode[512];
void rexxcheckcallbackhook (struct RexxMsg *msg, char *p)
{
if (!checkcallbackhookcode[0] || (strlen (p) < sizeof (checkcallbackhookcode)))
{
strcpy (checkcallbackhookcode, p);
replyRexxCmd (msg, 0L, 0L, "installed");
}
else
replyRexxCmd (msg, 0L, 0L, "notinstalled");
}
void invokerexxcheckcallbackhook (void)
{
if (checkcallbackhookcode[0] && !asyncRexxCmd (checkcallbackhookcode))
DisplayBeep (0);
checkcallbackhookcode[0] = '\0';
}
void rexxversion (struct RexxMsg *msg, char *p)
{
char buf[512];
int bufend = strlen(Version_ID+6);
int namesize;
int i;
strcpy(buf, Version_ID+6);
buf[bufend++] = '\n';
for (i = 0; rcl[i].name != NULL; i++)
{
namesize = strlen(rcl[i].name);
if ((namesize + bufend) > 511)
break;
strcpy (&(buf[bufend++]), " ");
strcpy (&(buf[bufend]), rcl[i].name);
bufend += namesize;
}
replyRexxCmd (msg, 0L, 0L, buf);
}
void rexxexit (struct RexxMsg *msg, char *p)
{
done = 1;
replyRexxCmd (msg, 0L, 0L, "bye");
}